package src.model.gameWorld;

import src.driver.PlayerObjectData;
import src.model.gameObject.GameObjectType;
import src.model.gameObject.GameObjectSubtype;
import src.model.gameObject.eventBrokers.HealthEventBroker;
import src.model.gameObject.eventBrokers.MeleeEventBroker;
import src.model.gameObject.eventBrokers.MoveEventBroker;
import src.model.gameWorld.pathfinding.astar.*;

import java.util.ArrayList;

/**
 * <b>Overview</b><br>
 * <p>When the game is started an the Model initialized, some object must
 * be responsible for creating and associating all the required objects
 * within the game model</p>
 * <br><br>
 * <b>Responsibilites</b><br>
 * <p>Creating and maintiang the game model</p>
 * <br><br>
 * <b>Collaborators</b>
 * <br><br>
 * <ul>
 * <li>PlayerObjectData - Subcontractor</li>
 * </ul>
 * <b>Implementor</b> - Brent<br>
 * <b>Tester</b> - Tim<br>
 * 
 * @author Brent
 *
 */
public class GameWorld
{

	private ArrayList<Player> players;
	private ActualMap actualMap;
	private LookupTable lookupTable;
	private CurrentPlayer currentPlayer;
	
	private GameWorldEventHandler gweh;
	private ModelEventHandler meh;
	private MoveEventBroker moveBroker;
	private HealthEventBroker healthBroker;
	private MeleeEventBroker meleeBroker;

	/**
	 * Creates a new game world, and all objects that that implies
	 * @param pods - objects represnting the players in the new world
	 * @param tileConfig - the tile configuraiton
	 */
	public GameWorld(PlayerObjectData[] pods, MapTileConfiguration tileConfig){
		
		// initializie the model
		actualMap = new ActualMap(10, 10, tileConfig);
		lookupTable = new LookupTable("data/model/lookupTableStats.lts");
		
		gweh = new GameWorldEventHandler();
		meh = new ModelEventHandler();
		
		moveBroker = new MoveEventBroker();
		healthBroker = new HealthEventBroker();
		meleeBroker = new MeleeEventBroker();

		actualMap = new ActualMap(Position.getXBoundary(), Position.getYBoundary(), tileConfig);

		AStarPathfinder.setMap(actualMap);
		AStarPathfinder.setMover(new MovementValidator(actualMap));

		players = new ArrayList<Player>();
	
		GameObjectFactory gof = new GameObjectFactory(actualMap, lookupTable);
		
		for(PlayerObjectData pod : pods)
		{
			Player player = new Player(pod, actualMap);
			players.add(player);	
		}

		currentPlayer = new CurrentPlayer(players);


		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(0,0));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(0,1));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.SAND, new Position(0,2));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(0,3));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.SAND, new Position(0,4));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(0,5));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.SAND, new Position(0,6));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(0,7));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(0,8));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(0,9));
		
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(1,1));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.SAND, new Position(1,2));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(1,3));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.SAND, new Position(1,4));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(1,5));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.SAND, new Position(1,6));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(1,7));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(1,8));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(1,9));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(1,0));
		
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(2,1));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.SAND, new Position(2,2));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(2,3));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.SAND, new Position(2,4));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.SAND, new Position(2,5));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.SAND, new Position(2,6));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(2,7));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(2,8));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(2,9));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(2,0));
		
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(3,1));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(3,2));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(3,3));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.SAND, new Position(3,4));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(3,5));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(3,6));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(3,7));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(3,8));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(3,9));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(3,0));
		
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.SAND, new Position(4,1));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.SAND, new Position(4,2));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.SAND, new Position(4,3));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(4,4));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(4,5));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(4,6));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(4,7));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(4,8));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(4,9));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.SAND, new Position(4,0));
		
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(5,1));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(5,2));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(5,3));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(5,4));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(5,5));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(5,6));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(5,7));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(5,8));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(5,9));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(5,0));
		
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(6,1));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(6,2));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(6,3));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(6,4));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(6,5));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(6,6));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(6,7));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(6,8));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(6,9));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(6,0));
		
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(7,1));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(7,2));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(7,3));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(7,4));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(7,5));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(7,6));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(7,7));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(7,8));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(7,9));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(7,0));
		
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(8,1));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(8,2));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(8,3));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(8,4));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(8,5));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(8,6));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(8,7));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(8,8));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(8,9));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(8,0));
		
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(9,1));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(9,2));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(9,3));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(9,4));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(9,5));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(9,6));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(9,7));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(9,8));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(9,9));
		gof.newGO(GameObjectType.TERRAIN, GameObjectSubtype.WATER, new Position(9,0));
		
		gof.newPGO(GameObjectType.UNIT, GameObjectSubtype.CORSAIR, new Position(0,0), currentPlayer.getCurrentPlayer());
		gof.newPGO(GameObjectType.UNIT, GameObjectSubtype.CORSAIR, new Position(0,5), currentPlayer.getCurrentPlayer());
		
		currentPlayer.getCurrentPlayer().beginTurn();
	}

	/**
	 * Returns a reference to the currently active player
	 * @return the current Player.
	 */
	public Player getCurrentPlayer()
	{
		return currentPlayer.getCurrentPlayer();
	}
}
